﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace game
{
    public class Glow : PostProcessEffect
    {
        public EffectParameter EP_gWorld { get; protected set; }
        public EffectParameter EP_gViewProj { get; protected set; }
        public EffectParameter EP_gTex { get; protected set; }
        public EffectParameter EP_gDepthTex { get; protected set; }

        public Effect ExtractEffect { get; protected set; }
        protected EffectTechnique extractEffectTech;

        protected Effect blurEffect;
        protected EffectTechnique blurEffectTechV;
        protected EffectTechnique blurEffectTechH;

        protected Effect depthRestoreEffect;
        protected EffectTechnique depthRestoreEffectTech;
        protected EffectParameter ep_gDepthTex_depthRestoreEffect;

        protected RenderTarget2D renderTarget1 = null;
        protected RenderTarget2D renderTarget2 = null;
        protected ResolveTexture2D resolveTexture = null;

        public Glow(Scene scene)
            : base(scene)
        {
            Type = PostProcessEffectType.GLOW;

            ExtractEffect = ShooterGame.Instance.Content.Load<Effect>("Effects\\GlowExtract");
            extractEffectTech = ExtractEffect.Techniques["GlowExtract"];
            EP_gWorld = ExtractEffect.Parameters["gWorld"];
            EP_gViewProj = ExtractEffect.Parameters["gViewProj"];
            EP_gTex = ExtractEffect.Parameters["gTex"];
            EP_gDepthTex = ExtractEffect.Parameters["gDepthTex"];

            blurEffect = ShooterGame.Instance.Content.Load<Effect>("Effects\\GlowBlur");
            blurEffectTechH = blurEffect.Techniques["GlowBlurHorizontal"];
            blurEffectTechV = blurEffect.Techniques["GlowBlurVertical"];

            depthRestoreEffect = ShooterGame.Instance.Content.Load<Effect>("Effects\\DepthRestore");
            depthRestoreEffectTech = depthRestoreEffect.Techniques["DepthRestore"];
            ep_gDepthTex_depthRestoreEffect = depthRestoreEffect.Parameters["gDepthTex"];
            depthRestoreEffect.CurrentTechnique = depthRestoreEffectTech;

            PresentationParameters pp = device.PresentationParameters;


            renderTarget1 = new RenderTarget2D(device, pp.BackBufferWidth / 2, pp.BackBufferHeight / 2,
                1, pp.BackBufferFormat, RenderTargetUsage.DiscardContents);
            renderTarget2 = new RenderTarget2D(device, pp.BackBufferWidth / 4, pp.BackBufferHeight / 4,
                1, pp.BackBufferFormat, RenderTargetUsage.DiscardContents);
            resolveTexture = new ResolveTexture2D(device, pp.BackBufferWidth, pp.BackBufferHeight,
                1, pp.BackBufferFormat);
        }

        public override void Draw(GameTime gameTime, List<GameObject> objects)
        {
            device.ResolveBackBuffer(resolveTexture);

            device.SetRenderTarget(0, renderTarget1);
            device.Clear(Color.Black);


            ep_gDepthTex_depthRestoreEffect.SetValue(scene.DepthTexture);
            ShooterGame.Instance.SpriteBatch.Begin(SpriteBlendMode.None,
                              SpriteSortMode.Immediate,
                              SaveStateMode.None);


            depthRestoreEffect.Begin();
            depthRestoreEffect.CurrentTechnique.Passes[0].Begin();

            ShooterGame.Instance.SpriteBatch.Draw(scene.DepthTexture,
                new Rectangle(0, 0,
                    renderTarget1.Width,
                    renderTarget1.Height),
                Color.White);
            ShooterGame.Instance.SpriteBatch.End();

            depthRestoreEffect.CurrentTechnique.Passes[0].End();
            depthRestoreEffect.End();




            ExtractEffect.CurrentTechnique = extractEffectTech;
            EP_gDepthTex.SetValue(scene.DepthTexture);
            foreach (GameObject obj in objects)
            {
                obj.DrawPostProcess(gameTime, this);
            }

            device.SetRenderTarget(0, null);

            blurEffect.CurrentTechnique = blurEffectTechV;
            DrawFullscreenQuad(renderTarget1.GetTexture(), renderTarget2, blurEffect);

            blurEffect.CurrentTechnique = blurEffectTechH;
            DrawFullscreenQuad(renderTarget2.GetTexture(), renderTarget1, blurEffect);

            DrawFullscreenQuad(resolveTexture, SpriteBlendMode.None);
            DrawFullscreenQuad(renderTarget1.GetTexture(), SpriteBlendMode.Additive);

        }
    }
}
